/****************************************************************
 * Fulguro
 * Copyright (C) 2004 Christophe Clienti
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************/

#include <string.h>
#include <math.h>
#include "flgrCoreArithVector.h"
#include "flgrCoreMalloc.h"
#include "flgrCoreDataIO.h"
#include "flgrCoreDispatch.h"
#include "flgrCoreGeometry.h"
#include "flgrCoreCopy.h"
#include "flgrCoreNhbFill.h"


/*!
 * \addtogroup group_fulguro_core
 * @{
 */




//////////////////////////////////////////////////////////////////
// Macro for different type of dilate_dtype_4_8_CONNEXITY
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_NATIVE_DILATE(dtype,					\
				 c00,c01,c02,				\
				 c10,c11,c12,				\
				 c20,c21,c22)				\
  FLGR_Data2D *nhbcopy;							\
  dtype **seodd;							\
  dtype **seeven;							\
  dtype **se;								\
  int i,j;								\
  int k,l;								\
  int m,n;								\
									\
  dtype valse;								\
									\
  FLGR_Vector *vecPixValue = flgr_vector_create(nhb->spp,nhb->type);	\
  FLGR_Vector *vecPixMax   = flgr_vector_create(nhb->spp,nhb->type);	\
  FLGR_Vector *vecSeValue  = flgr_vector_create(nhb->spp,nhb->type);	\
									\
  FLGR_DECLARE_FUNCTION;						\
									\
  nhbcopy = flgr2d_create_from(nhb);					\
  flgr2d_copy(nhbcopy,nhb);						\
									\
  seodd = (dtype**) flgr_malloc(sizeof(dtype*)*3);			\
  seodd[0] = (dtype*) flgr_malloc(sizeof(dtype)*3);			\
  seodd[1] = (dtype*) flgr_malloc(sizeof(dtype)*3);			\
  seodd[2] = (dtype*) flgr_malloc(sizeof(dtype)*3);			\
									\
  seeven = (dtype**) flgr_malloc(sizeof(dtype*)*3);			\
  seeven[0] = (dtype*) flgr_malloc(sizeof(dtype)*3);			\
  seeven[1] = (dtype*) flgr_malloc(sizeof(dtype)*3);			\
  seeven[2] = (dtype*) flgr_malloc(sizeof(dtype)*3);			\
									\
  flgr2d_set_data_array_##dtype(seodd,0,0,c02);				\
  flgr2d_set_data_array_##dtype(seodd,0,1,c01);				\
  flgr2d_set_data_array_##dtype(seodd,0,2,c00);				\
  flgr2d_set_data_array_##dtype(seodd,1,0,c10);				\
  flgr2d_set_data_array_##dtype(seodd,1,1,c11);				\
  flgr2d_set_data_array_##dtype(seodd,1,2,c12);				\
  flgr2d_set_data_array_##dtype(seodd,2,0,c22);				\
  flgr2d_set_data_array_##dtype(seodd,2,1,c21);				\
  flgr2d_set_data_array_##dtype(seodd,2,2,c20);				\
  									\
  flgr2d_set_data_array_##dtype(seeven,0,0,c00);			\
  flgr2d_set_data_array_##dtype(seeven,0,1,c01);			\
  flgr2d_set_data_array_##dtype(seeven,0,2,c02);			\
  flgr2d_set_data_array_##dtype(seeven,1,0,c10);			\
  flgr2d_set_data_array_##dtype(seeven,1,1,c11);			\
  flgr2d_set_data_array_##dtype(seeven,1,2,c12);			\
  flgr2d_set_data_array_##dtype(seeven,2,0,c20);			\
  flgr2d_set_data_array_##dtype(seeven,2,1,c21);			\
  flgr2d_set_data_array_##dtype(seeven,2,2,c22);			\
									\
  for(i=0; i<nhb->size_y; i++) {					\
    for(j=0; j<nhb->size_x; j++) {					\
									\
      flgr_vector_populate_from_scalar_##dtype(vecPixMax,0);		\
      									\
      for(k=(i-1),m=0 ; k<=(i+1) ; k++,m++) {				\
	if((k>=0) && (k<nhb->size_y)) {					\
	  for(l=(j-1),n=0 ; l<=(j+1) ; l++,n++) {			\
	    if((l>=0) && (l<nhb->size_x)) {				\
									\
	      se = (((i%2)==1) ? seodd:seeven);				\
									\
	      valse = flgr2d_get_data_array_##dtype(se,m,n);		\
	      flgr_vector_populate_from_scalar_##dtype(vecSeValue,	\
						       valse);		\
									\
	      flgr2d_get_data_vector_no_norm_##dtype(nhbcopy,k,l,	\
						     vecPixValue);	\
									\
	      flgr_vector_mult_##dtype(vecPixValue,			\
				       vecPixValue,vecSeValue);		\
									\
	      flgr_vector_sup_##dtype(vecPixMax,			\
				      vecPixMax,vecPixValue);		\
									\
	    }								\
	  }								\
	}								\
      }									\
									\
      flgr2d_set_data_vector_##dtype(nhb,i,j,vecPixMax);		\
 									\
    }									\
  }									\
									\
  flgr_vector_destroy(vecPixValue);					\
  flgr_vector_destroy(vecPixMax);					\
  flgr_vector_destroy(vecSeValue);					\
									\
  flgr2d_destroy(nhbcopy);						\
  flgr_free(seodd[0]);							\
  flgr_free(seodd[1]);							\
  flgr_free(seodd[2]);							\
  flgr_free(seodd);							\
  flgr_free(seeven[0]);							\
  flgr_free(seeven[1]);							\
  flgr_free(seeven[2]);							\
  flgr_free(seeven);							\
  return

void flgr2d_native_dilate_4_connexity_fgBIT(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgBIT,0,1,0,1,1,1,0,1,0);
}
void flgr2d_native_dilate_4_connexity_fgUINT8(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgUINT8,0,1,0,1,1,1,0,1,0);
}
void flgr2d_native_dilate_4_connexity_fgUINT16(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgUINT16,0,1,0,1,1,1,0,1,0);
}
void flgr2d_native_dilate_4_connexity_fgUINT32(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgUINT32,0,1,0,1,1,1,0,1,0);
}
void flgr2d_native_dilate_4_connexity_fgINT8(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgINT8,0,1,0,1,1,1,0,1,0);
}
void flgr2d_native_dilate_4_connexity_fgINT16(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgINT16,0,1,0,1,1,1,0,1,0);
}
void flgr2d_native_dilate_4_connexity_fgINT32(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgINT32,0,1,0,1,1,1,0,1,0);
}
void flgr2d_native_dilate_4_connexity_fgFLOAT32(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgFLOAT32,0,1,0,1,1,1,0,1,0);
}
void flgr2d_native_dilate_4_connexity_fgFLOAT64(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgFLOAT64,0,1,0,1,1,1,0,1,0);
}

//////////////////////////////////////////////////////////////////
/*! Native dilatation in 4 connexity (mainly used to fill neighborhoods definitions)
 *  @param nhb : a pointer to a FLGR_Data2D
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_native_dilate_4_connexity(FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;

  if(nhb==NULL) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  FLGR_DISPATCH_PROCEDURE(nhb->type,flgr2d_native_dilate_4_connexity,nhb);
}


void flgr2d_native_dilate_6_connexity_fgBIT(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgBIT,0,1,1,1,1,1,0,1,1);
}
void flgr2d_native_dilate_6_connexity_fgUINT8(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgUINT8,0,1,1,1,1,1,0,1,1);
}
void flgr2d_native_dilate_6_connexity_fgUINT16(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgUINT16,0,1,1,1,1,1,0,1,1);
}
void flgr2d_native_dilate_6_connexity_fgUINT32(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgUINT32,0,1,1,1,1,1,0,1,1);
}
void flgr2d_native_dilate_6_connexity_fgINT8(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgINT8,0,1,1,1,1,1,0,1,1);
}
void flgr2d_native_dilate_6_connexity_fgINT16(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgINT16,0,1,1,1,1,1,0,1,1);
}
void flgr2d_native_dilate_6_connexity_fgINT32(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgINT32,0,1,1,1,1,1,0,1,1);
}
void flgr2d_native_dilate_6_connexity_fgFLOAT32(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgFLOAT32,0,1,1,1,1,1,0,1,1);
}
void flgr2d_native_dilate_6_connexity_fgFLOAT64(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgFLOAT64,0,1,1,1,1,1,0,1,1);
}

//////////////////////////////////////////////////////////////////
/*! Native dilatation in 4 connexity (mainly used to fill neighborhoods definitions)
 *  @param nhb : a pointer to a FLGR_Data2D
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_native_dilate_6_connexity(FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;

  if(nhb==NULL) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  FLGR_DISPATCH_PROCEDURE(nhb->type,flgr2d_native_dilate_6_connexity,nhb);
}


void flgr2d_native_dilate_8_connexity_fgBIT(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgBIT,1,1,1,1,1,1,1,1,1);
}
void flgr2d_native_dilate_8_connexity_fgUINT8(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgUINT8,1,1,1,1,1,1,1,1,1);
}
void flgr2d_native_dilate_8_connexity_fgUINT16(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgUINT16,1,1,1,1,1,1,1,1,1);
}
void flgr2d_native_dilate_8_connexity_fgUINT32(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgUINT32,1,1,1,1,1,1,1,1,1);
}
void flgr2d_native_dilate_8_connexity_fgINT8(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgINT8,1,1,1,1,1,1,1,1,1);
}
void flgr2d_native_dilate_8_connexity_fgINT16(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgINT16,1,1,1,1,1,1,1,1,1);
}
void flgr2d_native_dilate_8_connexity_fgINT32(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgINT32,1,1,1,1,1,1,1,1,1);
}
void flgr2d_native_dilate_8_connexity_fgFLOAT32(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgFLOAT32,1,1,1,1,1,1,1,1,1);
}
void flgr2d_native_dilate_8_connexity_fgFLOAT64(FLGR_Data2D *nhb) {
  FLGR_MACRO_NATIVE_DILATE(fgFLOAT64,1,1,1,1,1,1,1,1,1);
}

//////////////////////////////////////////////////////////////////
/*! Native dilatation in 8 connexity (mainly used to fill neighborhoods definitions)
 *  @param nhb : a pointer to a FLGR_Data2D
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_native_dilate_8_connexity(FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;

  if(nhb==NULL) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  FLGR_DISPATCH_PROCEDURE(nhb->type,flgr2d_native_dilate_8_connexity,nhb);
}






//////////////////////////////////////////////////////////////////
// Macro for different type of flgr1d_fill_neighborhood
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_FILL_1D_SHP(dtype)					\
  FLGR_Vector *vec1 = flgr_vector_create(nhb->spp,nhb->type);		\
									\
  flgr_vector_populate_from_scalar_##dtype(vec1,1);			\
									\
  if(nhb->shape == FLGR_LINE) {						\
    flgr1d_draw_line_##dtype(nhb,nhb->length/2-width/2,width,vec1);	\
  }									\
									\
  flgr_vector_destroy(vec1);						\
									\
  return


void flgr1d_fill_neighborhood_fgBIT(FLGR_Data1D *nhb, FLGR_Shape shape, int width) {
  FLGR_MACRO_FILL_1D_SHP(fgBIT);
}
void flgr1d_fill_neighborhood_fgUINT8(FLGR_Data1D *nhb, FLGR_Shape shape, int width) {
  FLGR_MACRO_FILL_1D_SHP(fgUINT8);
}
void flgr1d_fill_neighborhood_fgUINT16(FLGR_Data1D *nhb, FLGR_Shape shape, int width) {
  FLGR_MACRO_FILL_1D_SHP(fgUINT16);
}
void flgr1d_fill_neighborhood_fgUINT32(FLGR_Data1D *nhb, FLGR_Shape shape, int width) {
  FLGR_MACRO_FILL_1D_SHP(fgUINT32);
}
void flgr1d_fill_neighborhood_fgINT8(FLGR_Data1D *nhb, FLGR_Shape shape, int width) {
  FLGR_MACRO_FILL_1D_SHP(fgINT8);
}
void flgr1d_fill_neighborhood_fgINT16(FLGR_Data1D *nhb, FLGR_Shape shape, int width) {
  FLGR_MACRO_FILL_1D_SHP(fgINT16);
}
void flgr1d_fill_neighborhood_fgINT32(FLGR_Data1D *nhb, FLGR_Shape shape, int width) {
  FLGR_MACRO_FILL_1D_SHP(fgINT32);
}
void flgr1d_fill_neighborhood_fgFLOAT32(FLGR_Data1D *nhb, FLGR_Shape shape, int width) {
  FLGR_MACRO_FILL_1D_SHP(fgFLOAT32);
}
void flgr1d_fill_neighborhood_fgFLOAT64(FLGR_Data1D *nhb, FLGR_Shape shape, int width) {
  FLGR_MACRO_FILL_1D_SHP(fgFLOAT64);
}

//////////////////////////////////////////////////////////////////
/*! Fill a neighborhood definition with a shape
 *  @param nhb    : a pointer to a FLGR_Data1D
 *  @param shape  : shape of the structuring element (FLGR_LINE or FLGR_USER_SHAPE)
 *  @param width : shape width
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr1d_fill_neighborhood(FLGR_Data1D *nhb, FLGR_Shape shape, int width) {
  if(nhb==NULL) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  FLGR_DISPATCH_PROCEDURE(nhb->type,flgr1d_fill_neighborhood,nhb,shape,width);
}




//////////////////////////////////////////////////////////////////
// Macro for different type of flgr2d_fill_neighborhood
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_FILL_2D_SHP(dtype)					\
  FLGR_Vector *vec1 = flgr_vector_create(nhb->spp,nhb->type);		\
  FLGR_Data2D *tmp = flgr2d_create_from(nhb);				\
  int h=nhb->size_y;							\
  int w=nhb->size_x;							\
  int size=((height<width) ? height:width);				\
  double size_square  = ((double) (size/2)) / (1+sqrt(2));		\
  double size_square2 = floor(size_square);				\
  int nbsqr = (int) ((size_square-size_square2) < 0.5f ?		\
		     size_square2 : (size_square2+1));			\
  int i;								\
  									\
  flgr2d_clear_all(nhb);						\
  flgr_vector_populate_from_scalar_##dtype(vec1,1);			\
   									\
  if(shape == FLGR_HEX) {						\
    flgr2d_set_data_vector_##dtype(nhb,h/2,w/2,vec1);			\
    for(i=0;i<size/2;i++) flgr2d_native_dilate_6_connexity_##dtype(nhb);\
    if( ((size/2)%2)==1 ) {						\
      flgr2d_fill_nhb_even_rows_##dtype(tmp,nhb);			\
      flgr2d_copy(nhb,tmp);						\
    }									\
    									\
  }else if(shape == FLGR_RECT) {					\
    flgr2d_draw_filled_rectangle_##dtype(nhb,w/2-width/2, h/2-height/2,	\
					 width,height,vec1);		\
									\
  }else if(shape == FLGR_DIAMOND) {					\
    flgr2d_set_data_vector_##dtype(nhb,h/2,w/2,vec1);			\
    for(i=0;i<size/2;i++)						\
      flgr2d_native_dilate_4_connexity_##dtype(nhb);			\
									\
  }else if(shape == FLGR_OCTAGON) {					\
    flgr2d_set_data_vector_##dtype(nhb,h/2,w/2,vec1);			\
    for(i=0 ; i<size/2-nbsqr ; i++)					\
      flgr2d_native_dilate_4_connexity_##dtype(nhb);			\
    									\
    for(i=0 ; i<nbsqr ; i++)						\
      flgr2d_native_dilate_8_connexity_##dtype(nhb);			\
 									\
  }else if(shape == FLGR_DISC) {					\
    flgr2d_draw_disc_##dtype(nhb,w/2,h/2,size/2,vec1);			\
									\
  }else if(shape == FLGR_ELLIPSE) {					\
    flgr2d_draw_filled_ellipse_##dtype(nhb,w/2,h/2,			\
				       width/2,height/2,vec1);		\
									\
  }else if(shape == FLGR_SLASH) {					\
    flgr2d_draw_line_##dtype(nhb, w/2-width/2, height-1+h/2-height/2,	\
			     width-1+w/2-width/2, h/2-height/2, vec1);	\
									\
  }else if(shape == FLGR_BSLASH) {					\
    flgr2d_draw_line_##dtype(nhb,w/2-width/2, h/2-height/2,		\
			     width-1+w/2-width/2, height-1+h/2-height/2,vec1); \
									\
  }else if(shape == FLGR_CROSS) {					\
    flgr2d_draw_vertical_line_##dtype(nhb,w/2,h/2-height/2,height,vec1); \
    flgr2d_draw_horizontal_line_##dtype(nhb,w/2-width/2,h/2,width,vec1); \
									\
  }else if(shape == FLGR_CROSSX) {					\
    flgr2d_draw_line_##dtype(nhb,w/2-width/2, height-1+h/2-height/2,	\
			     width-1+w/2-width/2,h/2-height/2,vec1);	\
    flgr2d_draw_line_##dtype(nhb, w/2-width/2, h/2-height/2,		\
			     width-1+w/2-width/2,height-1+h/2-height/2,vec1); \
  }									\
									\
  flgr_vector_destroy(vec1);						\
  flgr2d_destroy(tmp);							\
									\
  return

void flgr2d_fill_neighborhood_fgBIT(FLGR_Data2D *nhb, FLGR_Shape shape, int width, int height) {
  FLGR_MACRO_FILL_2D_SHP(fgBIT);
}
void flgr2d_fill_neighborhood_fgUINT8(FLGR_Data2D *nhb, FLGR_Shape shape, int width, int height) {
  FLGR_MACRO_FILL_2D_SHP(fgUINT8);
}
void flgr2d_fill_neighborhood_fgUINT16(FLGR_Data2D *nhb, FLGR_Shape shape, int width, int height) {
  FLGR_MACRO_FILL_2D_SHP(fgUINT16);
}
void flgr2d_fill_neighborhood_fgUINT32(FLGR_Data2D *nhb, FLGR_Shape shape, int width, int height) {
  FLGR_MACRO_FILL_2D_SHP(fgUINT32);
}
void flgr2d_fill_neighborhood_fgINT8(FLGR_Data2D *nhb, FLGR_Shape shape, int width, int height) {
  FLGR_MACRO_FILL_2D_SHP(fgINT8);
}
void flgr2d_fill_neighborhood_fgINT16(FLGR_Data2D *nhb, FLGR_Shape shape, int width, int height) {
  FLGR_MACRO_FILL_2D_SHP(fgINT16);
}
void flgr2d_fill_neighborhood_fgINT32(FLGR_Data2D *nhb, FLGR_Shape shape, int width, int height) {
  FLGR_MACRO_FILL_2D_SHP(fgINT32);
}
void flgr2d_fill_neighborhood_fgFLOAT32(FLGR_Data2D *nhb, FLGR_Shape shape, int width, int height) {
  FLGR_MACRO_FILL_2D_SHP(fgFLOAT32);
}
void flgr2d_fill_neighborhood_fgFLOAT64(FLGR_Data2D *nhb, FLGR_Shape shape, int width, int height) {
  FLGR_MACRO_FILL_2D_SHP(fgFLOAT64);
}


//////////////////////////////////////////////////////////////////
/*! Fill a neighborhood definition with a shape
 *  @param nhb    : a pointer to a FLGR_Data2D
 *  @param shape  : shape of the structuring element
 *  @param width  : shape width
 *  @param height : shape height
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_fill_neighborhood(FLGR_Data2D *nhb, FLGR_Shape shape, int width, int height) {
  if(nhb==NULL) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if(nhb->shape!=shape) {
    POST_WARNING("given shape does not correspond to FLGR_Data2D shape\n");
  }

  if(width>nhb->size_x) {
    POST_WARNING("width too high\n");
    width=nhb->size_x;
  }

  if(width<0) {
    POST_WARNING("width < 0\n");
    width=0;
  }

  if(width%2==0) {
    width++;
  }

  if(height>nhb->size_y) {
    POST_WARNING("height too high\n");
    height=nhb->size_y;
  }

  if(height<0) {
    POST_WARNING("height < 0\n");
    height=0;
  }

  if(height%2==0) {
    height++;
  }



 
  FLGR_DISPATCH_PROCEDURE(nhb->type,flgr2d_fill_neighborhood,nhb,shape,width,height);

}



//! @}
